module.exports = function (args) {
    const {
        threads,
        rootPath,
        DefinePlugin,
        ProvidePlugin,
        VueLoaderPlugin,
        webpackVariable,
        CopyWebpackPlugin,
        HtmlWebpackPlugin,
        MiniCssExtractPlugin,
        ForkTsCheckerWebpackPlugin
    } = args
    return {
        /*
        * webpack模式
        * development、production、none 三种模式，mode默认为production，项目中正常使用development、production
        * webpack serve 模式下，mode默认为development
        * webpack build 模式下，mode默认为production
        * */
        mode: webpackVariable.mode,
        /*
        * 入口文件，可以是一个字符串，也可以是一个对象(可配置多页应用)
        * entry: rootPath + '/src/main.ts'
        * entry: { app: rootPath + '/src/main.ts', other: rootPath + '/src/main.ts' },
        * */
        entry: rootPath + '/src/main.ts',
        /*
        * 输出文件
        * path: 输出文件路径
        * filename: 输出文件名称
        * clean: 删除dist目录下文件，每次构建前删除
        * chunkFilename: 输出代码块文件名称，比如动态导入的组件、第三方插件等
        * assetModuleFilename: 输出静态资源文件名称
        * Vue组件<style>标签中的内容变动会导致其所属的当前chunk的chunkHash值变动。因为Webpack在打包过程中会将组件的整个内容（包括JavaScript逻辑、模板以及<style>中的CSS）视为一个整体来处理。当任何部分的内容发生变化时，Webpack会重新构建该组件相关的chunk，并重新计算其chunkHash
        * */
        output: {
            path: rootPath + '/dist',
            filename: 'js/[name].[chunkhash:8].js',
            chunkFilename: "js/[name].[chunkhash:8].chunk.js",
            assetModuleFilename: 'images/[fullhash][ext][query]',
            clean: true,
        },
        /*
        * 缓存配置，用于加速构建速度
        * type: 缓存类型，可选值：memory（内存）、filesystem（文件系统）
        * name: 缓存名称，用于区分缓存
        * buildDependencies:{}
        * config: [__filename] 当webpack配置文件变化时刷新缓存
        * */
        cache: {
            type: 'filesystem',
            name: webpackVariable.mode + '-' + webpackVariable.runEnv,
            buildDependencies: {
                config: [
                    __filename,
                ]
            }
        },
        /*
        * 模块解析
        * extensions: 模块后缀名
        * alias: 模块别名
        * */
        resolve: {
            extensions: ['.vue', '.ts', '.tsx', '.js', '.jsx'],
            alias: {
                '@': rootPath + '/src',
            }
        },
        /*
        * 模块加载器
        * */
        module: {
            rules: [
                {
                    oneOf: [
                        {
                            test: /\.(jpe?g|png|gif)$/i,
                            type: 'asset', // 在asset模式下，会在asset/resource(导出 文件名.hash.[png/jpg/gif]) 和 asset/inline(自动转成base64) 选择
                            parser: {
                                dataUrlCondition: {
                                    maxSize: 10 * 1024,
                                },
                            },
                        },
                        {
                            test: /\.s?css$/,
                            exclude: /(node_modules)/,
                            use: [
                                {
                                    loader: webpackVariable.mode === 'development' ? 'style-loader' : MiniCssExtractPlugin.loader,
                                },
                                {
                                    loader: 'css-loader',
                                    options: {
                                        importLoaders: 1  // 当前以@import 'index.css' 时，需要向上加载几次loader（postcss-loader、sass-loader）
                                    }
                                },
                                {
                                    loader: 'postcss-loader',
                                },
                                {
                                    loader: 'sass-loader',
                                    options: {
                                        additionalData: `@import '@/assets/css/common.scss';`, // 引入每个组件中
                                    },
                                }],
                        },
                        {
                            test: /\.js$/,
                            exclude: file => (
                                /node_modules/.test(file) &&
                                !/\.vue\.js/.test(file)
                            ),
                            use: [
                                {
                                    loader: 'thread-loader',  // 项目过大时，可以开启多线程加速
                                    options: {
                                        workers: threads,
                                    }
                                },
                                {
                                    loader: 'babel-loader',
                                    options: {
                                        cacheDirectory: true
                                    }
                                }
                            ]
                        },
                        {
                            test: /\.tsx?$/,  // https://github.com/TypeStrong/ts-loader/issues/1618
                            exclude: /node_modules/,
                            use: [
                                {
                                    loader: 'babel-loader',
                                    options: {
                                        cacheDirectory: true
                                    }
                                },
                                {
                                    loader: 'ts-loader',
                                    options: {
                                        transpileOnly: true, // 在处理 TypeScript 代码时只做转译（transpile）而跳过类型检查（type checking）, 类型检查交给 ForkTsCheckerWebpackPlugin插件处理
                                        appendTsSuffixTo: [/\.vue$/], // 当从 .vue 文件导入时，自动追加.ts或.tsx后缀: xxx.vue.ts、xxx.vue.tsx
                                    }
                                },
                            ]
                        }
                    ]
                },
                {
                    test: /\.vue$/,
                    loader: 'vue-loader',  // webpack5中，vue-loader用来处理.vue文件。vue-loader会自动处理.vue文件中的<style>、<template>、<script>标签，并调用相应的loader进行处理。
                },
            ],
        },
        plugins: [
            // 生成index.html模板
            new HtmlWebpackPlugin({
                template: rootPath + '/public/index.html',
                favicon: rootPath + '/public/favicon.ico',
                filename: 'index.html',
            }),
            // 生成全局变量
            new DefinePlugin({
                webpackVariable: JSON.stringify(webpackVariable) // 替代cross-env插件功能
            }),
            // 复制静态资源
            new CopyWebpackPlugin({
                patterns: [
                    {
                        from: rootPath + '/public/static',
                        to: rootPath + '/dist/static'
                    },
                ],
            }),
            // 自动加载模块
            new ProvidePlugin({
                http: rootPath + '/src/assets/utils/http.ts'
            }),
            // ts类型检查
            new ForkTsCheckerWebpackPlugin(),
            new VueLoaderPlugin(), // vue-loader需要这个插件, 用来处理.vue文件。当遇到 .vue 文件时，VueLoaderPlugin 会调用 vue-loader 对其进行解析。vue-loader 会将 .vue 文件拆分为三个部分：模板（<template>）、脚本（<script>）和样式（<style>）。
        ],
        performance: {
            maxAssetSize: 500 * 1024, // 设置打包后文件大小最大值 500 KiB
        },
    }
}
